package com.bank.basic.common.aop;


import com.bank.common.exceptionUtil.CustomedException;
import com.bank.common.resultUtil.ResultCodeEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;

/**
 * @author Cejay1314
 * @version 1.0
 * @create 2022/11/8 14:18
 */

//public class CExceptionCaptureAspect {
//}
@Aspect
@Component
//@Slf4j
public class CExceptionCaptureAspect {
    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     *     @Pointcut("execution(* com.crud.com.bank.user.controller.BlogController.getBlogById())")
     *     上面的这种是excution表达式，比如说我并不想开发一个专门的注解，我就想在某一个或者某一类的方法上添加这个aop，那就可以通过excution表达式来做
     * @Pointcut("execution(public * com.crud.com.bank.user.controller.*.*(..))")
     * ..两个点表明多个，*代表一个， 上面表达式代表切入com.xhx.springboot.controller包下的所有类的所有方法，
     * 方法参数不限，返回类型不限。 其中访问修饰符可以不写，不能用*，，第一个*代表返回类型不限，第二个*表示所有类，第三个*表示所有方法，..两个点表示方法里的参数不限
     * 有一点非常重要，Spring的AOP只能支持到方法级别的切入。换句话说，切入点只能是某个方法
     */
    @Pointcut("execution(* com.bank.basic.controller..*(..))")
    public void ExceptionCapturPointcut() {
    }

    @Around("ExceptionCapturPointcut()")
    public Object processException(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        /**
         * 环绕通知=前置+目标方法执行+后置，proceed方法就是用于启动目标方法执行的
         * Proceedingjoinpoint 继承了 JoinPoint。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要，这个是aop代理链执行的方法。
         * 暴露出这个方法，就能支持 com.bank.user.aop:around 这种切面（而其他的几种切面只需要用到JoinPoint，，这也是环绕通知和前置、后置通知方法的一个最大区别。这跟切面类型有关）
         * */
        try{
            Object res = proceedingJoinPoint.proceed();
            response.addHeader("state", ResultCodeEnum.SUCCESS.getCode().toString());
            return res;
        }catch (CustomedException e) {
            response.addHeader("state", e.getCode().toString());
        }
        return null;
    }

}

